package crud.dao.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import common.utils.BeanUtil;

import crud.client.data.Colonne;
import crud.client.data.ColonneToOne;
import crud.client.data.DataView;
import crud.client.data.DependenceToOne;
import crud.client.data.Donnee;
import crud.client.data.LigneDonnee;
import crud.client.data.Table;
import crud.dao.DonneeDAO;
import crud.server.util.DataConversionUtil;

public class DonneeDAOImpl extends HibernateDaoSupport implements DonneeDAO
{

	@Override
	public List<LigneDonnee> loadLigneDonneeList(Table table, List<Colonne> colonneList)
	{
		// Les lignes de la table
		List<?> ligneList = getHibernateTemplate().loadAll(BeanUtil.forName(table.getMappingClassName()));

		// Parcourt des données et arrangement dans une Map
		List<LigneDonnee> ligneDonneeList = new ArrayList<LigneDonnee>();
		
		// Parcourt des lignes reéues
		for (Object ligne : ligneList)
		{
			LigneDonnee ligneDonnee = new LigneDonnee();
			ligneDonneeList.add(ligneDonnee);
			
			// Parcourt des colonnes et création des données
			for (Colonne colonne : colonneList)
			{
				Donnee donnee = new Donnee();
				ligneDonnee.add(donnee);
				donnee.setColonne(colonne);
				DataView dataView = new DataView();
				dataView.setData((Serializable) BeanUtil.getProperty(ligne, colonne.getProperty()));
				dataView.setLabel(DataConversionUtil.donneeToString(colonne, dataView.getData()));
				dataView.setKey(DataConversionUtil.donneeToKey(dataView.getData()));

				donnee.setDataView(dataView);
			}
		}
		
		return ligneDonneeList;
	}
	
	
	@Override
//	@Transactional
	public void updateData(Table table, List<LigneDonnee> donneeListToDelete, List<LigneDonnee> donneeListToSave)
	{
		
		// Suppression des anciennes lignes de la table
		getHibernateTemplate().deleteAll(ligneDonneeListToDataList(table, donneeListToDelete));

		// Ajout des nouvelles lignes
		getHibernateTemplate().saveOrUpdateAll(ligneDonneeListToDataList(table, donneeListToSave));
	}
	
	private List<? super Serializable> ligneDonneeListToDataList(Table table, List<LigneDonnee> ligneDonneeList)
	{
		// Transformation de la liste des données
		List<? super Serializable> dataList = new ArrayList<Serializable>();
		
		for (LigneDonnee ligneDonnee : ligneDonneeList)
		{
			dataList.add(ligneDonneeToData(table, ligneDonnee));
		}
		
		return dataList;
	}

	private Serializable ligneDonneeToData(Table table, LigneDonnee ligneDonnee)
	{
			Serializable data = (Serializable) BeanUtil.newInstance(BeanUtil.forName(table.getMappingClassName()));
			for (Donnee donnee : ligneDonnee.getDonneeList())
			{
				Serializable value = donnee.getColonne().getDataConverter().convertDataToColonneDataType(donnee.getDataView().getData());
				BeanUtil.setProperty(data, donnee.getColonne().getProperty(), value);
			}
		return data;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<DataView> loadAll(ColonneToOne colonneToOne)
	{
		List<DataView> dataViewList = new ArrayList<DataView>();
		List<Serializable> resultList = (List<Serializable>) getHibernateTemplate().loadAll(colonneToOne.getTargetType().getClass());
		
		for (Serializable result : resultList)
		{
			DataView dataView = new DataView();
			dataViewList.add(dataView);
			
			dataView.setKey(DataConversionUtil.donneeToKey(result));
			dataView.setData(result);
			dataView.setLabel(DataConversionUtil.donneeToString(colonneToOne, result));
		}
		
		return dataViewList;
		
		
	}

	public boolean isDataUsed(Table table, LigneDonnee ligneDonneeToCheck)
	{
		// Si la table n'a pas de dépendances --> pas de dépendances
		if (table.getDependingEntities().isEmpty())
		{
			return false;
		}
		Serializable dataToCheck = ligneDonneeToData(table, ligneDonneeToCheck);
		
		// UN PEU BIDOUILLEUX !!! 
		// A REFAIRE !!!!
		for (DependenceToOne dependenceToOne : table.getDependingEntities())
		{
			String dataToCheckPkProperty = BeanUtil.getIdFields(dataToCheck.getClass()).get(0).getName();
			
			String query  = "select count(*) from " + dependenceToOne.getDependentClassName() + 
			" where " + dependenceToOne.getProperty() + "." + dataToCheckPkProperty + " = " + BeanUtil.getProperty(dataToCheck, dataToCheckPkProperty).toString();
			
			if ((Long) getHibernateTemplate().find(query).get(0) > 0)
			{
				return true;
			}
		}
		return false;
	}
}
